package org.xyf.IM.config;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import java.util.ArrayList;
import java.util.List;

public class SentinelConfig {

    public static final String RPC_RESOURCE = "rpc_resource";

    public static void initRules(){
        initFlowRules();
        initDegradeRules();
    }

    private static void initFlowRules(){
        List<FlowRule> rules = new ArrayList<>();
        addRpcFlowRules(rules);
        FlowRuleManager.loadRules(rules);
    }


    private static void initDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        addRpcDegradeRules(rules);
        DegradeRuleManager.loadRules(rules);
    }



    /**
     * 配置rpc接口的熔断降级规则
     */
    private static void addRpcFlowRules(List<FlowRule> rules){
        FlowRule rpcRrule = new FlowRule();
        rpcRrule.setResource(RPC_RESOURCE);
        rpcRrule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // rpcRrule limit QPS to 20.
        rpcRrule.setCount(20);
        rules.add(rpcRrule);
    }

    /**
     * 慢调用比例 (SLOW_REQUEST_RATIO)：选择以慢调用比例作为阈值，需要设置允许的慢调用 RT（即最大的响应时间），请求的响应时间大于该值则统计为慢调用。
     * 当单位统计时长（statIntervalMs）内请求数目大于设置的最小请求数目，并且慢调用的比例大于阈值，则接下来的熔断时长内请求会自动被熔断。
     * 经过熔断时长后熔断器会进入探测恢复状态（HALF-OPEN 状态），若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断，若大于设置的慢调用 RT 则会再次被熔断。
     */
    private static void addRpcDegradeRules(List<DegradeRule> rules){
        DegradeRule rpcRrule = new DegradeRule(RPC_RESOURCE)
                .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())//按慢调用比例进行降级
                .setCount(50) // 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用)
                .setTimeWindow(10) //熔断时长 单位:秒
                .setSlowRatioThreshold(0.6) //慢调用比例阈值
                .setMinRequestAmount(100) //熔断触发的最小请求数，请求数小于该值时即使异常比率超出阈值也不会熔断
                .setStatIntervalMs(20*1000);//统计时长 20秒
        rules.add(rpcRrule);
    }
}
